package comtgl.demo.utils;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.google.gson.*;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;

public class RFC5545JsonConverter {

    // RFC 5545重复规则解析器和转换器
    public static class RRuleConverter {
        private static final Pattern RRULE_PATTERN = Pattern.compile("([A-Z]+)=([^;]+)");
        private static final DateTimeFormatter DATE_TIME_FORMAT = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'");
        private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyyMMdd");

        // RRULE字符串转RRule对象
        public static RRule fromString(String rruleStr) {
            if (rruleStr == null || !rruleStr.startsWith("FREQ=")) {
                throw new IllegalArgumentException("Invalid RRULE format: " + rruleStr);
            }

            RRule rrule = new RRule();
            Matcher matcher = RRULE_PATTERN.matcher(rruleStr);

            while (matcher.find()) {
                String key = matcher.group(1);
                String value = matcher.group(2);

                switch (key) {
                    case "FREQ":
                        rrule.setFreq(FreqType.fromString(value));
                        break;
                    case "INTERVAL":
                        rrule.setInterval(Integer.parseInt(value));
                        break;
                    case "COUNT":
                        rrule.setCount(Integer.parseInt(value));
                        break;
                    case "UNTIL":
                        try {
                            rrule.setUntil(LocalDateTime.parse(value, DATE_TIME_FORMAT));
                        } catch (DateTimeParseException e) {
                            // 尝试解析为纯日期格式
                            rrule.setUntil(LocalDateTime.parse(value + "T000000Z", DATE_TIME_FORMAT));
                        }
                        break;
                    case "BYDAY":
                        rrule.setByday(Arrays.asList(value.split(",")));
                        break;
                    case "BYMONTH":
                        rrule.setBymonth(parseIntegerList(value));
                        break;
                    case "BYSETPOS":
                        rrule.setBysetpos(Integer.parseInt(value));
                        break;
                    case "WKST":
                        rrule.setWkst(Weekday.fromString(value));
                        break;
                    // 可扩展更多参数...
                    default:
                        // 忽略未知参数
                        break;
                }
            }

            return rrule;
        }

        // RRule对象转RRULE字符串
        public static String toString(RRule rrule) {
            if (rrule.getFreq() == null) {
                throw new IllegalArgumentException("FREQ is required for RRULE");
            }

            StringBuilder sb = new StringBuilder();
            sb.append("FREQ=").append(rrule.getFreq().name());

            if (rrule.getInterval() != 1) {
                sb.append(";INTERVAL=").append(rrule.getInterval());
            }

            if (rrule.getCount() != null) {
                sb.append(";COUNT=").append(rrule.getCount());
            }

            if (rrule.getUntil() != null) {
                sb.append(";UNTIL=").append(rrule.getUntil().format(DATE_TIME_FORMAT));
            }

            if (!rrule.getByday().isEmpty()) {
                sb.append(";BYDAY=").append(String.join(",", rrule.getByday()));
            }

            if (!rrule.getBymonth().isEmpty()) {
                sb.append(";BYMONTH=").append(joinIntegers(rrule.getBymonth()));
            }

            if (rrule.getBysetpos() != null) {
                sb.append(";BYSETPOS=").append(rrule.getBysetpos());
            }

            if (rrule.getWkst() != Weekday.MONDAY) {
                sb.append(";WKST=").append(rrule.getWkst().getSerializedName());
            }

            return sb.toString();
        }

        private static List<Integer> parseIntegerList(String value) {
            String[] parts = value.split(",");
            List<Integer> result = new ArrayList<>();
            for (String part : parts) {
                result.add(Integer.parseInt(part));
            }
            return result;
        }

        private static String joinIntegers(List<Integer> list) {
            return list.stream()
                    .map(Object::toString)
                    .collect(java.util.stream.Collectors.joining(","));
        }
    }

    // JSON与RRule对象的转换器
    public static class RRuleJsonConverter {
        private static final Gson gson;

        static {
            GsonBuilder builder = new GsonBuilder()
                    .setPrettyPrinting()
                    .registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter());
            gson = builder.create();
        }

        // RRule对象转JSON字符串
        public static String toJson(RRule rrule) {
            return gson.toJson(rrule);
        }

        // JSON字符串转RRule对象
        public static RRule fromJson(String json) {
            return gson.fromJson(json, RRule.class);
        }

        // JSON字符串转VEvent对象
        public static VEvent eventFromJson(String json) {
            return gson.fromJson(json, VEvent.class);
        }

        // VEvent对象转JSON字符串
        public static String eventToJson(VEvent event) {
            return gson.toJson(event);
        }
    }

    // 重复频率类型
    public enum FreqType {
        @SerializedName("SECONDLY")
        SECONDLY("SECONDLY"),
        @SerializedName("MINUTELY")
        MINUTELY("MINUTELY"),
        @SerializedName("HOURLY")
        HOURLY("HOURLY"),
        @SerializedName("DAILY")
        DAILY("DAILY"),
        @SerializedName("WEEKLY")
        WEEKLY("WEEKLY"),
        @SerializedName("MONTHLY")
        MONTHLY("MONTHLY"),
        @SerializedName("YEARLY")
        YEARLY("YEARLY");

        private final String serializedName;

        FreqType(String serializedName) {
            this.serializedName = serializedName;
        }

        public String getSerializedName() {
            return serializedName;
        }

        public static FreqType fromString(String value) {
            return FreqType.valueOf(value.toUpperCase());
        }
    }

    // 星期类型
    public enum Weekday {
        @SerializedName("SU") SUNDAY("SU"),
        @SerializedName("MO") MONDAY("MO"),
        @SerializedName("TU") TUESDAY("TU"),
        @SerializedName("WE") WEDNESDAY("WE"),
        @SerializedName("TH") THURSDAY("TH"),
        @SerializedName("FR") FRIDAY("FR"),
        @SerializedName("SA") SATURDAY("SA");

        private final String serializedName;

        Weekday(String serializedName) {
            this.serializedName = serializedName;
        }

        public String getSerializedName() {
            return serializedName;
        }

        public static Weekday fromString(String value) {
            return Weekday.valueOf(value.toUpperCase());
        }
    }

    // 表示RRULE的Java类
    public static class RRule {
        private FreqType freq;
        private int interval = 1;
        private Integer count;
        private LocalDateTime until;
        private List<String> byday = new ArrayList<>();
        private List<Integer> bymonth = new ArrayList<>();
        private Integer bysetpos;
        private Weekday wkst = Weekday.MONDAY;

        // Getters and setters
        public FreqType getFreq() { return freq; }
        public void setFreq(FreqType freq) { this.freq = freq; }

        public int getInterval() { return interval; }
        public void setInterval(int interval) { this.interval = interval; }

        public Integer getCount() { return count; }
        public void setCount(Integer count) { this.count = count; }

        public LocalDateTime getUntil() { return until; }
        public void setUntil(LocalDateTime until) { this.until = until; }

        public List<String> getByday() { return byday; }
        public void setByday(List<String> byday) { this.byday = byday; }

        public List<Integer> getBymonth() { return bymonth; }
        public void setBymonth(List<Integer> bymonth) { this.bymonth = bymonth; }

        public Integer getBysetpos() { return bysetpos; }
        public void setBysetpos(Integer bysetpos) { this.bysetpos = bysetpos; }

        public Weekday getWkst() { return wkst; }
        public void setWkst(Weekday wkst) { this.wkst = wkst; }
    }

    // 表示完整的iCalendar事件的类
    public static class VEvent {
        private String uid;
        private LocalDateTime dtstart;
        private LocalDateTime dtend;
        private RRule rrule;

        // Getters and setters
        public String getUid() { return uid; }
        public void setUid(String uid) { this.uid = uid; }

        public LocalDateTime getDtstart() { return dtstart; }
        public void setDtstart(LocalDateTime dtstart) { this.dtstart = dtstart; }

        public LocalDateTime getDtend() { return dtend; }
        public void setDtend(LocalDateTime dtend) { this.dtend = dtend; }

        public RRule getRrule() { return rrule; }
        public void setRrule(RRule rrule) { this.rrule = rrule; }
    }

    // LocalDateTime的JSON序列化/反序列化适配器
    public static class LocalDateTimeAdapter implements JsonSerializer<LocalDateTime>, JsonDeserializer<LocalDateTime> {
        private static final DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME;

        @Override
        public JsonElement serialize(LocalDateTime src, java.lang.reflect.Type typeOfSrc, JsonSerializationContext context) {
            return new JsonPrimitive(src.format(formatter));
        }

        @Override
        public LocalDateTime deserialize(JsonElement json, java.lang.reflect.Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            return LocalDateTime.parse(json.getAsString(), formatter);
        }
    }

    // 主类：用于测试双向转换功能
    public static void main(String[] args) {
        try {
            // 示例1：RRULE字符串 → JSON → RRULE字符串
            System.out.println("=== 示例1: RRULE → JSON → RRULE ===");
            String rruleStr = "FREQ=WEEKLY;BYDAY=MO,WE;UNTIL=20250831T235959Z";
            System.out.println("原始RRULE: " + rruleStr);

            // 转换为RRule对象
            RRule rrule = RRuleConverter.fromString(rruleStr);
            // 转换为JSON
            String json = RRuleJsonConverter.toJson(rrule);
            System.out.println("转换后的JSON:\n" + json);

            // 从JSON转回RRule对象
            RRule rruleFromJson = RRuleJsonConverter.fromJson(json);
            // 转回RRULE字符串
            String rruleStrBack = RRuleConverter.toString(rruleFromJson);
            System.out.println("转回的RRULE: " + rruleStrBack);

            // 示例2：包含事件的完整转换
            System.out.println("\n=== 示例2: 完整事件转换 ===");
            VEvent event = new VEvent();
            event.setUid("meeting-123");
            event.setDtstart(LocalDateTime.of(2025, 6, 2, 9, 0));
            event.setDtend(LocalDateTime.of(2025, 6, 2, 10, 0));
            event.setRrule(rrule);

            // 事件转JSON
            String eventJson = RRuleJsonConverter.eventToJson(event);
            System.out.println("事件JSON:\n" + eventJson);

            // JSON转事件
            VEvent eventFromJson = RRuleJsonConverter.eventFromJson(eventJson);
            String eventRruleStr = RRuleConverter.toString(eventFromJson.getRrule());
            System.out.println("从JSON恢复的RRULE: " + eventRruleStr);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}